﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using GameSchool.DAL;
using GameSchool.Models;
using GameSchool.Models.AccountModels;
using GameSchool.ViewModels.Account;

namespace GameSchool.Controllers
{
    [HandleError]
    public class AccountController : Controller
    {
        private IAccountRepository m_rep;

        public AccountController()
        {
            m_rep = new AccountRepository(new gsEntities());
        }

        public AccountController(IAccountRepository rep)
        {
            m_rep = rep;
        }

        // GET: /Account/Create
        [Authorize(Roles = "Admin")]
        public ActionResult Create()
        {
            var viewModel = new CreateViewModel();
            viewModel.userModel = new UserModel();
            viewModel.departmentDegrees = new SelectList(m_rep.GetDepartmentDegrees(), "DepartmentDegreeID", "DepartmentDegreeName");
            viewModel.postalCodeRegions = new SelectList(m_rep.GetPostalCodes(), "PostalCode", "PostalCodeRegion");

            return View(viewModel);
        }

        // POST: /Account/Create
        [HttpPost]
        [Authorize(Roles = "Admin")]
        public ActionResult Create(UserModel userModel)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                Membership.CreateUser(userModel.UserName, userModel.Password, userModel.Email, null, null, true, null, out createStatus);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    // Ná í userId og uppfæra allar persónuupplýsingarnar fyrir hann
                    var memberShipUser = Membership.GetUser(userModel.UserName);
                    userModel.UserId = (Guid)memberShipUser.ProviderUserKey;
                    m_rep.UpdateUser(userModel);

                    // Bæta usernum í MemberShip Role
                    if (!Roles.GetRolesForUser(userModel.UserName).Any())
                    {
                        Roles.AddUserToRole(userModel.UserName, userModel.UserType.ToString());
                    }

                    return RedirectToAction("List", "Account", new { createdUser = userModel.UserName });
                }
                else
                {
                    ModelState.AddModelError("", ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            var viewModel = new CreateViewModel();
            viewModel.userModel = userModel;
            viewModel.departmentDegrees = new SelectList(m_rep.GetDepartmentDegrees(), "DepartmentDegreeID", "DepartmentDegreeName");
            viewModel.postalCodeRegions = new SelectList(m_rep.GetPostalCodes(), "PostalCode", "PostalCodeRegion");

            return View(viewModel);
        }

        // GET: /Account/ChangePassword
        [Authorize(Roles = "Admin")]
        public ActionResult ChangePassword(Guid userId)
        {
            ViewBag.UserName = Membership.GetUser(userId).UserName;

            return View();
        }

        // POST: /Account/ChangePassword
        [Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model, Guid userId)
        {
            if (ModelState.IsValid)
            {

                // ChangePassword will throw an exception rather
                // than return false in certain failure scenarios.
                bool changePasswordSucceeded;
                var userToChangePassword = Membership.GetUser(userId);

                try
                {
                    changePasswordSucceeded = userToChangePassword.ChangePassword(model.OldPassword, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    return RedirectToAction("List", new { passwordChangedForUser = userToChangePassword.UserName });
                }
                else
                {
                    ModelState.AddModelError("", "Núverandi lykilorð var ekki rétt skráð, eða nýja lykilorðið er ógilt.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // GET: /Account/ChangePasswordSuccess
        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        // GET: /Account/Edit
        [Authorize(Roles = "Admin")]
        public ActionResult Edit(Guid userId)
        {
            var viewModel = new EditViewModel();
            viewModel.userModel = m_rep.GetUserById(userId);
            viewModel.departmentDegrees = new SelectList(m_rep.GetDepartmentDegrees(), "DepartmentDegreeID", "DepartmentDegreeName", viewModel.userModel.DepartmentDegreeId);
            viewModel.postalCodeRegions = new SelectList(m_rep.GetPostalCodes(), "PostalCode", "PostalCodeRegion", viewModel.userModel.PostalCode);

            return View(viewModel);
        }

        // POST: /Account/Edit
        [HttpPost]
        [Authorize(Roles = "Admin")]
        public ActionResult Edit(UserModel userModel, Guid userId)
        {
            // Bæta inn upplýsingum í módelið sem vantar
            userModel.UserId = userId;
            // Treystum ekki því sem kemur úr forminu, svo við náum í userName úr gagnagrunninum
            var dbUser = m_rep.GetUserById(userId);
            userModel.UserName = dbUser.UserName;
            userModel.UserType = dbUser.UserType;

            // Því að Password er Required field, þá þurfum við að fjarlægja það úr ModelState svo módelið sé valid
            ModelState.Remove("userModel.Password");
            ModelState.Remove("userModel.UserName");
            ModelState.Remove("userModel.UserType");

            if (ModelState.IsValid)
            {
                m_rep.UpdateUser(userModel);

                // Þarf ekki að vista í þessu tilfelli, en yfirleitt þarf það
                //m_rep.Save();

                return RedirectToAction("List", "Account", new { updatedUser = userModel.UserName });
            }

            // If we got this far, something failed, redisplay form
            var viewModel = new EditViewModel();
            viewModel.userModel = m_rep.GetUserById(userId);
            viewModel.departmentDegrees = new SelectList(m_rep.GetDepartmentDegrees(), "DepartmentDegreeID", "DepartmentDegreeName");
            viewModel.postalCodeRegions = new SelectList(m_rep.GetPostalCodes(), "PostalCode", "PostalCodeRegion");

            return View(viewModel);
        }

        // GET: /Account/List
        [Authorize(Roles = "Admin")]
        public ActionResult List(string updatedUser, string createdUser, string passwordChangedForUser)
        {
            var viewModel = new ListViewModel();
            viewModel.userListModel = m_rep.GetUsers();
            viewModel.userJustUpdated = updatedUser;
            viewModel.userJustCreated = createdUser;
            viewModel.userJustChangedPassword = passwordChangedForUser;

            return View(viewModel);
        }

        // GET: /Account/LogOn
        public ActionResult LogOn()
        {
            return View();
        }

        // POST: /Account/LogOn
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (Membership.ValidateUser(model.UserName, model.Password))
                {
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "Notandanafnið eða lykilorðið er ekki rétt skráð.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // GET: /Account/LogOff
        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();

            return RedirectToAction("Index", "Home");
        }

        #region Status Codes
        private static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://go.microsoft.com/fwlink/?LinkID=177550 for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "Notandanafn er nú þegar til. Vinsamlega reyndu annað notandanafn.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "Það er nú þegar til notandi með sama tölvupóstfang. Vinsamlega skráðu annað tölvupóstfang.";

                case MembershipCreateStatus.InvalidPassword:
                    return "Lykilorðið er ógilt. Vinsamlega skráðu gilt lykilorð.";

                case MembershipCreateStatus.InvalidEmail:
                    return "Innslegið tölvupóstfang er ógilt. Vinsamlega lagfærðu og reyndu aftur.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "Svarið við lykilorðs endurheimtu spurningunni var rangt. Vinsamlega reyndu aftur.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "Lykilorðs endurheimtu spurningin var ógild. Vinsamlega reyndu aftur.";

                case MembershipCreateStatus.InvalidUserName:
                    return "Innslegið notandanafn er ógilt. Vinsamlega lagfærðu og reyndu aftur.";

                case MembershipCreateStatus.ProviderError:
                    return "Öryggisstjórinn skilaði villu. Vinsamlega farðu yfir innslátt og reyndu aftur. Ef þetta vandamál kemur aftur upp, vinsamlega hafðu samband við kerfisstjóra.";

                case MembershipCreateStatus.UserRejected:
                    return "Hætt hefur verið við að búa til notanda. Vinsamlega farðu yfir innslátt og reyndu aftur. Ef þetta vandamál kemur aftur upp, vinsamlega hafðu samband við kerfisstjóra.";

                default:
                    return "Óþekkt villa hefur komið upp. Vinsamlega farðu yfir innslátt og reyndu aftur. Ef þetta vandamál kemur aftur upp, vinsamlega hafðu samband við kerfisstjóra.";
            }
        }
        #endregion
    }
}
